#include "file_manager_impl.h" // Include the implementation header
#include "file_index.h"
#include "utils_log.h"
#include "common_config_manager.h"
#include <filesystem>
#include <fstream>
#include <ctime>
#include <nlohmann/json.hpp>
#include <algorithm>
#include <stdexcept> // For potential exceptions in GetInstance

namespace fs = std::filesystem;

namespace El {
namespace FileManager {

// FileInfo 序列化/反序列化实现
nlohmann::json FileInfo::ToJson() const
{
    nlohmann::json json;
    json["id"] = id;
    json["name"] = name;
    json["type"] = type;
    json["path"] = path;
    json["size"] = size;
    json["is_deleted"] = is_deleted;
    json["last_access"] = last_access;
    json["origin"] = origin;
    return json;
}

std::optional<FileInfo> FileInfo::FromJson(const nlohmann::json &json)
{
    FileInfo info;
    try {
        info.id = json.value("id", "");
        info.name = json.value("name", "");
        info.type = json.value("type", "");
        info.path = json.value("path", "");
        info.size = json.value("size", 0);
        info.is_deleted = json.value("is_deleted", false);
        info.last_access = json.value("last_access", 0);
        info.origin = json.value("origin", "user");

        // 验证必要字段
        if (info.id.empty()) {
            EL_ERROR("Parsed file info has empty ID from JSON: {}", json.dump());
            return std::nullopt;
        }

        // 验证 origin 字段
        if (info.origin != "preset" && info.origin != "user") {
            EL_WARN("Invalid origin value '{}' in file info, using default 'user'", info.origin);
            info.origin = "user"; // 如果 origin 无效，设为默认值 "user"
        }

    } catch (const nlohmann::json::type_error &e) {
        EL_ERROR("Failed to parse file info due to type error: {} in JSON: {}", e.what(), json.dump());
        return std::nullopt;
    } catch (const std::exception &e) {
        EL_ERROR("Failed to parse file info from json: {} in JSON: {}", e.what(), json.dump());
        return std::nullopt;
    }
    return info;
}

// --- FileManagerImpl Implementation ---

// Constructor
FileManagerImpl::FileManagerImpl()
{
    // Initialization logic moved to Initialize() method
}

// Destructor
FileManagerImpl::~FileManagerImpl() = default; // Or add cleanup if needed

IFileManager &IFileManager::GetInstance()
{
    static FileManagerImpl instance;
    return instance;
}

void FileManagerImpl::InitConfig()
{
    // 从配置文件读取配置
    nlohmann::json config = Common::ConfigManager::GetInstance().GetConfig("/file_manager");
    if (config.is_null()) {
        EL_WARN("Config for '/file_manager' not found or invalid, using defaults.");
        presetDir_ = "/mnt/assets/audio";
        userDir_ = "/mnt/data/file";
        maxFilesPerType_ = 100;
    } else {
        // 如果 config 不为 null，则尝试从中读取值
        presetDir_ = config.value("preset_dir", "/mnt/assets/audio");
        userDir_ = config.value("user_dir", "/mnt/data/file");
        maxFilesPerType_ = config.value("max_files_per_type", 100);
    }

    EL_INFO("Preset dir: {}, User dir: {}, Max files per type: {}", presetDir_, userDir_, maxFilesPerType_);
}

// Initialize (now a public method of FileManagerImpl)
bool FileManagerImpl::Start()
{
    // Prevent re-initialization
    if (initialized_.load()) {
        EL_WARN("FileManager already initialized.");
        return true;
    }

    InitConfig();

    // 确保目录存在
    if (!EnsureDirectoryExists(userDir_) || !EnsureDirectoryExists("/mnt/config")) {
        EL_ERROR("Failed to create required directories");
        return false;
    }

    // 初始化单个索引文件
    fileIndex_ = std::make_unique<FileIndex>("/mnt/config/file_index.json");
    if (!fileIndex_->Initialize()) {
        EL_ERROR("Failed to initialize file index");
        return false;
    }

    // 检查预制文件目录
    if (fs::exists(presetDir_)) {
        // 扫描预制文件
        EL_INFO("Scanning preset files directory");
        if (!fileIndex_->ScanFiles(presetDir_, "preset")) {
            EL_ERROR("Failed to scan preset files");
            return false;
        }
    } else {
        EL_WARN("Preset directory does not exist: {}", presetDir_);
    }

    // 扫描用户文件目录
    if (fs::exists(userDir_)) {
        EL_INFO("Scanning user files directory");
        if (!fileIndex_->ScanFiles(userDir_, "user")) {
            EL_ERROR("Failed to scan user files");
            return false;
        }
    }

    EL_INFO("File manager initialized successfully");
    initialized_.store(true); // Mark as initialized
    return true;
}

// GetFileList (now a public method of FileManagerImpl)
std::vector<FileInfo> FileManagerImpl::GetFileList(FileType type, bool includeDeleted)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return {};
    }
    return fileIndex_->GetFileList(type, includeDeleted);
}

// GetFileInfo (now a public method of FileManagerImpl)
bool FileManagerImpl::GetFileInfo(const std::string &fileId, FileInfo &outInfo)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }

    if (fileIndex_->GetFileInfo(fileId, outInfo)) {
        // 更新最后访问时间
        outInfo.last_access = static_cast<int64_t>(std::time(nullptr));

        // 更新文件信息
        fileIndex_->UpdateFileInfo(outInfo);

        return true;
    }
    return false;
}

bool FileManagerImpl::GetFileInfoByName(const std::string &fileName, FileInfo &outInfo)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }

    // 获取所有文件列表
    auto fileList = GetFileList(FileType::ALL, false);
    
    // 遍历文件列表，查找匹配文件名的文件
    for (const auto &file : fileList) {
        if (file.name == fileName) {
            outInfo = file;
            
            // 更新最后访问时间
            outInfo.last_access = static_cast<int64_t>(std::time(nullptr));
            
            // 更新文件信息
            fileIndex_->UpdateFileInfo(outInfo);
            
            return true;
        }
    }
    
    // 如果没有找到匹配的文件，返回false
    return false;
}

// DeleteFile (now a public method of FileManagerImpl)
bool FileManagerImpl::DeleteFile(const std::string &fileId)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }

    FileInfo fileInfo;
    if (!fileIndex_->GetFileInfo(fileId, fileInfo)) {
        EL_ERROR("File not found for deletion: {}", fileId);
        return false;
    }

    // 判断是预制文件还是用户文件（通过 origin 字段）
    if (fileInfo.origin == "preset") {
        // 预制文件只做虚拟删除
        return fileIndex_->MarkFileAsDeleted(fileId);
    } else if (fileInfo.origin == "user") {
        // 用户文件物理删除
        try {
            if (fs::exists(fileInfo.path)) {
                fs::remove(fileInfo.path);
            }
            return fileIndex_->RemoveFileInfo(fileId);
        } catch (const std::exception &e) {
            EL_ERROR("Failed to delete file {}: {}", fileInfo.path, e.what());
            return false;
        }
    } else {
        EL_ERROR("Invalid file origin: {}", fileInfo.origin);
        return false;
    }
}

// RestoreFile (now a public method of FileManagerImpl)
bool FileManagerImpl::RestoreFile(const std::string &fileId)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }

    FileInfo fileInfo;
    if (!fileIndex_->GetFileInfo(fileId, fileInfo)) {
        EL_ERROR("File not found for restoration: {}", fileId);
        return false;
    }

    // 只有预制文件可以恢复
    if (fileInfo.origin == "preset") {
        return fileIndex_->RestoreDeletedFile(fileId);
    } else {
        EL_ERROR("Only preset files can be restored: {}", fileId);
        return false;
    }
}

// CreateFile (now a public method of FileManagerImpl)
std::string FileManagerImpl::CreateFile(const std::string &fileName, FileType type)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return "";
    }

    // 检查文件类型限制
    if (!CheckFileTypeLimit(type)) {
        EL_ERROR("File type limit reached for type: {}", static_cast<int>(type));
        return "";
    }

    // 生成唯一ID
    std::string fileId = std::to_string(std::time(nullptr)) + "_" + fileName;

    // 创建临时文件路径
    std::string tempPath = GetTempFilePath(fileId);

    // 存储活跃文件信息
    {
        std::lock_guard<std::mutex> lock(activeFilesMutex_);
        activeFiles_[fileId] = tempPath;
    }

    return fileId;
}

// WriteFileBlock (now a public method of FileManagerImpl)
bool FileManagerImpl::WriteFileBlock(const std::string &fileId, const std::string &block, bool isLastBlock)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }
    std::string tempPath;
    EL_DEBUG("开始写入文件块 - fileId: {}, blockSize: {}, isLastBlock: {}", fileId, block.size(), isLastBlock);

    // 获取临时文件路径
    {
        std::lock_guard<std::mutex> lock(activeFilesMutex_);
        auto it = activeFiles_.find(fileId);
        if (it == activeFiles_.end()) {
            EL_ERROR("File not found for writing: {}", fileId);
            return false;
        }
        tempPath = it->second;
        EL_DEBUG("获取到临时文件路径: {}", tempPath);
    }

    try {
        // 检查存储空间
        if (!CheckStorageSpace(block.size())) {
            EL_ERROR("Not enough storage space for writing block");
            return false;
        }
        EL_DEBUG("存储空间检查通过");

        // 写入文件块
        std::ofstream file(tempPath, std::ios::binary | std::ios::app);
        if (!file.is_open()) {
            EL_ERROR("Failed to open temp file for writing: {}", tempPath);
            return false;
        }
        EL_DEBUG("临时文件打开成功，准备写入数据块");

        file.write(block.data(), block.size());
        file.close();
        EL_DEBUG("数据块写入完成");

        // 如果是最后一个块，完成文件写入
        if (isLastBlock) {
            EL_DEBUG("处理最后一个数据块");
            // 提取原始文件名和类型
            size_t pos = fileId.find('_');
            std::string originalName = (pos != std::string::npos) ? fileId.substr(pos + 1) : fileId;
            EL_DEBUG("提取的原始文件名: {}", originalName);

            // 确定文件类型
            std::string typeStr;
            FileType fileType = FileType::IMAGE; // 默认图像类型
            std::string extension = fs::path(originalName).extension().string();
            EL_DEBUG("文件扩展名: {}", extension);

            if (!extension.empty()) {
                std::transform(extension.begin(), extension.end(), extension.begin(),
                               [](unsigned char c) { return std::tolower(c); });

                if (extension == ".mp3" || extension == ".wav" || extension == ".ogg" || extension == ".flac" ||
                    extension == ".aac") {
                    typeStr = "audio";
                    fileType = FileType::AUDIO;
                } else if (extension == ".mp4" || extension == ".avi" || extension == ".mov" || extension == ".mkv" ||
                           extension == ".webm" || extension == ".wmv") {
                    typeStr = "video";
                    fileType = FileType::VIDEO;
                } else {
                    typeStr = "image";
                    fileType = FileType::IMAGE;
                }
            } else {
                typeStr = "image";
            }
            EL_DEBUG("确定的文件类型: {}", typeStr);

            // 生成最终文件路径
            std::string finalPath = GetFinalFilePath(originalName, fileType);
            EL_DEBUG("生成的最终文件路径: {}", finalPath);

            // 移动临时文件到最终位置
            if (!MoveToFinalPath(tempPath, finalPath)) {
                EL_ERROR("Failed to move temp file to final location");
                return false;
            }
            EL_DEBUG("临时文件已成功移动到最终位置");

            // 创建文件信息
            FileInfo fileInfo;
            fileInfo.id = fileId;
            fileInfo.name = originalName;
            fileInfo.type = typeStr;
            fileInfo.path = finalPath;
            fileInfo.size = fs::file_size(finalPath);
            fileInfo.is_deleted = false;
            fileInfo.last_access = static_cast<int64_t>(std::time(nullptr));
            fileInfo.origin = "user"; // 新创建的文件是用户文件
            EL_DEBUG("创建的文件信息 - size: {}, path: {}, origin: {}", fileInfo.size, fileInfo.path, fileInfo.origin);

            // 添加到索引
            if (!fileIndex_->AddFileInfo(fileInfo)) {
                EL_ERROR("Failed to add file info to index");
                return false;
            }
            EL_DEBUG("文件信息已添加到索引");

            // 清理活跃文件记录
            {
                std::lock_guard<std::mutex> lock(activeFilesMutex_);
                activeFiles_.erase(fileId);
                EL_DEBUG("已从活跃文件列表中移除");
            }

            EL_INFO("File successfully created: {}", finalPath);
        }

        return true;
    } catch (const std::exception &e) {
        EL_ERROR("Failed to write file block: {}", e.what());
        return false;
    }
}

// GetStorageInfo (now a public method of FileManagerImpl)
bool FileManagerImpl::GetStorageInfo(int32_t &totalSpace, int32_t &usedSpace, int32_t &availableSpace)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false; // Or provide default/error values
    }
    try {
        fs::space_info spaceInfo = fs::space(userDir_);
        totalSpace = spaceInfo.capacity;
        availableSpace = spaceInfo.available;
        usedSpace = spaceInfo.capacity - spaceInfo.available;
        return true;
    } catch (const std::exception &e) {
        EL_ERROR("Failed to get storage info: {}", e.what());
        return false;
    }
}

// GetFilePath (now a public method of FileManagerImpl)
std::string FileManagerImpl::GetFilePath(const std::string &fileId)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return "";
    }
    FileInfo fileInfo;
    if (fileIndex_->GetFileInfo(fileId, fileInfo)) {
        // 如果文件已被标记为删除，返回空
        if (fileInfo.is_deleted) {
            return "";
        }
        return fileInfo.path;
    }
    return "";
}

// ReadFileBlock (now a public method of FileManagerImpl)
bool FileManagerImpl::ReadFileBlock(const std::string &fileId, int chunkIndex, int32_t chunkSize, std::string &outData)
{
    if (!initialized_.load()) {
        EL_ERROR("FileManager not initialized.");
        return false;
    }
    try {
        // 获取文件信息
        FileInfo fileInfo;
        if (!fileIndex_->GetFileInfo(fileId, fileInfo)) {
            EL_ERROR("File not found for reading: {}", fileId);
            return false;
        }

        // 检查文件是否已被删除
        if (fileInfo.is_deleted) {
            EL_ERROR("File has been deleted: {}", fileId);
            return false;
        }

        // 打开文件
        std::ifstream file(fileInfo.path, std::ios::binary);
        if (!file.is_open()) {
            EL_ERROR("Failed to open file for reading: {}", fileInfo.path);
            return false;
        }

        // 计算读取位置和大小
        int32_t offset = chunkIndex * chunkSize;
        if (offset >= fileInfo.size) {
            EL_ERROR("Invalid chunk index: {} for file size: {}", chunkIndex, fileInfo.size);
            return false;
        }

        // 计算实际需要读取的大小（最后一块可能不足chunkSize）
        int32_t remainingSize = fileInfo.size - offset;
        int32_t actualChunkSize = std::min(chunkSize, remainingSize);

        // 定位到指定位置
        file.seekg(offset);

        // 读取数据
        outData.resize(actualChunkSize);
        file.read(&outData[0], actualChunkSize);

        // 检查是否读取成功
        if (file.fail()) {
            EL_ERROR("Failed to read file chunk: {}", fileInfo.path);
            return false;
        }

        // 更新最后访问时间
        fileInfo.last_access = static_cast<int64_t>(std::time(nullptr));
        fileIndex_->UpdateFileInfo(fileInfo);

        return true;
    } catch (const std::exception &e) {
        EL_ERROR("Exception while reading file block: {}", e.what());
        return false;
    }
}

// --- Private Helper Methods of FileManagerImpl ---

bool FileManagerImpl::CheckStorageSpace(int32_t requiredSpace)
{
    try {
        fs::space_info spaceInfo = fs::space(userDir_);
        return spaceInfo.available > static_cast<uintmax_t>(requiredSpace);
    } catch (const std::exception &e) {
        EL_ERROR("Failed to check storage space: {}", e.what());
        return false;
    }
}

bool FileManagerImpl::CheckFileTypeLimit(FileType type)
{
    // 获取指定类型的文件列表数量
    auto fileList = fileIndex_->GetFileList(type, false);
    return fileList.size() < static_cast<size_t>(maxFilesPerType_);
}

bool FileManagerImpl::EnsureDirectoryExists(const std::string &path)
{
    try {
        if (!fs::exists(path)) {
            return fs::create_directories(path);
        }
        return true;
    } catch (const std::exception &e) {
        EL_ERROR("Failed to create directory {}: {}", path, e.what());
        return false;
    }
}

std::string FileManagerImpl::GetTempFilePath(const std::string &fileId)
{
    // 确保临时目录存在
    std::string tempDir = userDir_ + "/temp";
    EnsureDirectoryExists(tempDir);

    // 生成临时文件路径
    return tempDir + "/" + fileId + ".tmp";
}

std::string FileManagerImpl::GetFinalFilePath(const std::string &fileName, FileType type)
{
    // 根据文件类型确定目录
    std::string typeDir;
    switch (type) {
        case FileType::AUDIO:
            typeDir = "/audio";
            break;
        case FileType::VIDEO:
            typeDir = "/video";
            break;
        case FileType::IMAGE:
        default:
            typeDir = "/image";
            break;
    }

    // 完整路径
    std::string fullDir = userDir_ + typeDir;
    EnsureDirectoryExists(fullDir);

    // 返回最终文件路径
    return fullDir + "/" + fileName;
}

bool FileManagerImpl::MoveToFinalPath(const std::string &tempPath, const std::string &finalPath)
{
    try {
        // 如果目标文件已存在，先删除
        if (fs::exists(finalPath)) {
            fs::remove(finalPath);
        }

        // 移动文件
        fs::rename(tempPath, finalPath);
        return true;
    } catch (const std::exception &e) {
        EL_ERROR("Failed to move file from {} to {}: {}", tempPath, finalPath, e.what());
        return false;
    }
}

} // namespace FileManager
} // namespace El